package com.glsc.ngateway.filetransfer.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.glsc.ngateway.common.api.filetransfer.dto.SmbFileDto;
import com.glsc.ngateway.filetransfer.exception.FileTransferException;
import jcifs.smb.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

@Service
public class FileTransferService {

    private static final Logger logger = LoggerFactory.getLogger(FileTransferService.class);


    public List<SmbFileDto> listFiles(String ip, String userAccount, String passwd, String shareFolderName) {
        List<SmbFileDto> fileList = new ArrayList<>();
        try {
            SmbFile remoteFile = this.tryConnectSmb(ip, userAccount, passwd, shareFolderName, null);
            if (remoteFile.isDirectory()) {
                for (SmbFile smbfile : remoteFile.listFiles("*")) {
                    SmbFileDto fileDto = new SmbFileDto();
                    fileDto.setName(smbfile.getName());
                    fileDto.setSize(smbfile.getContentLength());
                    fileDto.setLastModified(DateUtil.date(smbfile.getLastModified()).toStringDefaultTimeZone());
                    fileDto.setDirectoryFlag(smbfile.isDirectory());
                    fileList.add(fileDto);
                }
            } else {
                logger.info("SupplierDrawingList: Directory Name:" + shareFolderName + " is Not a Directory ");
            }
        } catch (Exception e) {
            logger.error("异常", e);
            throw FileTransferException.error("读取远程目录件失败!" + e.getLocalizedMessage());
        }
        logger.info("文件列表：" + fileList);
        return fileList;
    }

    public boolean checkFileExist(String ip, String userAccount, String passwd, String shareFolderName, String remoteFileName) {
        boolean result = false;
        try {
            SmbFile remoteFile = this.tryConnectSmb(ip, userAccount, passwd, shareFolderName, remoteFileName);
            result = remoteFile.exists();
        } catch (Exception e) {
            logger.error("异常", e);
            throw FileTransferException.error("检查远程文件失败!" + e.getLocalizedMessage());
        }
        return result;
    }

    public void putFile(String ip, String userAccount, String passwd, String shareFolderName, String cover, MultipartFile file) {
        InputStream in = null;
        OutputStream out = null;
        boolean uploadTempSuccessFlag = false;
        String originFileName = null;
        String tmpFileName = null;
        SmbFile remoteTempFile = null;
        try {
            originFileName = file.getOriginalFilename();
            tmpFileName = originFileName + ".tmp";
            remoteTempFile = this.tryConnectSmb(ip, userAccount, passwd, shareFolderName, tmpFileName);
            in = new BufferedInputStream(file.getInputStream());
            out = new BufferedOutputStream(new SmbFileOutputStream(remoteTempFile));
            IoUtil.copy(in, out, 4096);
            uploadTempSuccessFlag = true;
        } catch (Exception e) {
            logger.error("异常", e);
            throw FileTransferException.error("推送文件失败!" + e.getLocalizedMessage());
        } finally {
            IoUtil.close(out);
            IoUtil.close(in);
            if (uploadTempSuccessFlag) {//上传成功，临时文件改为正式文件名称
                try {
                    Thread.sleep(100);
                    SmbFile remoteOkFile = this.tryConnectSmb(ip, userAccount, passwd, shareFolderName, originFileName);
                    if (remoteOkFile.exists() && cover.equals("Y")) {
                        logger.warn(originFileName + "已存在,进行覆盖上传!");
                        remoteOkFile.delete();
                        logger.info("修改为正式文件名称：" + originFileName + ",临时文件名称=" + tmpFileName);
                    }
                    remoteTempFile.renameTo(remoteOkFile);
                } catch (InterruptedException | SmbException e) {
                    logger.error("异常", e);
                    throw FileTransferException.error("临时文件重命名失败!" + e.getMessage());
                }
            }
        }

    }

    public void getFile(String ip, String userAccount, String passwd, String shareFolderName, String remoteFileName, OutputStream out) {
        InputStream in = null;
        try {
            NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(null, userAccount, passwd);
            SmbFile remoteFile = new SmbFile("smb://" + ip + "/" + shareFolderName + "/" + remoteFileName, auth);
            in = new BufferedInputStream(new SmbFileInputStream(remoteFile));
            out = new BufferedOutputStream(out);
            IoUtil.copy(in, out, 2048);
        } catch (Exception e) {
            logger.error("异常", e);
            throw FileTransferException.error("下载文件失败!" + e.getLocalizedMessage());
        } finally {
            IoUtil.close(in);
        }
        System.out.println(String.format("下载文件{//%s/%s/%s}至本地目录：{%s}成功", ip, shareFolderName, remoteFileName));

    }

    public void deleteFile(String ip, String userAccount, String passwd, String shareFolderName, String remoteFileName) {
        try {
            SmbFile remoteFile = this.tryConnectSmb(ip, userAccount, passwd, shareFolderName, remoteFileName);
            if (remoteFile.exists()) {//检查删除成功
                remoteFile.delete();
                System.out.println("删除文件：" + shareFolderName + "/" + remoteFileName);
            }
        } catch (SmbException e) {
            logger.error("异常", e);
            throw FileTransferException.error("下载文件失败!" + e.getLocalizedMessage());
        }
    }

    /**
     * Description: 检查参数的合法性以及验证登录
     *
     * @param ip              目标IP地址
     * @param shareFolderName 共享文件夹
     * @param remoteFileName  远程文件名称（选填）
     */
    private SmbFile tryConnectSmb(String ip, String userAccount, String passwd, String shareFolderName, String remoteFileName) {
        NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(null, userAccount, passwd);
        SmbFile remoteFile = null;
        try {
            StringBuilder smbURLBuilder = new StringBuilder();
            smbURLBuilder.append("smb://");
            smbURLBuilder.append(ip);
            smbURLBuilder.append("/");

            if (StrUtil.isNotBlank(shareFolderName)) {
                smbURLBuilder.append(shareFolderName).append("/");
            }

            if (StrUtil.isNotBlank(remoteFileName)) {
                smbURLBuilder.append(remoteFileName).append("/");
            }
            logger.info("smb url=" + smbURLBuilder);
            remoteFile = new SmbFile(smbURLBuilder.toString(), auth);
            logger.info("connected to " + smbURLBuilder + " !shareFolderName=" + shareFolderName);
            remoteFile.connect();
            logger.info("connected to " + ip + " success!shareFolderName=" + shareFolderName);
            return remoteFile;
        } catch (IOException e) {
            logger.error("异常", e);
            throw new RuntimeException("远程文件连接失败!" + e.getMessage());
        }
    }
}
